openapi: 3.0.3
info:
  title: QoD for enhanced communication
  description: |
    The Quality-On-Demand (QoD) API provides programmable interface for developers and other users (capabilities consumers) to request stable latency or throughput managed by Telco networks without the necessity to have an in-depth knowledge of the 4G/5G system or the overall complexity of the Telecom Systems.

    # Introduction

    Industrial (IoT), VR/Gaming, live video streaming, autonomous driving and many other scenarios demand network communication quality and are sensitive to any change in transmission conditions. Being able to request a stable latency (reduced jitter) or prioritized throughput from the network can improve user experience substantially.

    The QoD API offers the application developers the capability to request for stable latency (reduced jitter) or throughput for some specified application data flows between application clients (within a user device) and Application Servers (backend services). The developer has a pre-defined set of Quality of Service (QoS) profiles which they could choose from depending on their latency or throughput requirements.

    ![QoD API Overview](https://raw.githubusercontent.com/camaraproject/QualityOnDemand/main/documentation/API_documentation/resources/QoD_latency_overview.PNG)

    The usage of the API is based on QoS session resources, which can be created (based on available QoS profiles), queried and deleted. The deletion of a requested session can be triggered by the API consumer or can be triggered automatically. The automatic process is triggered either when the requested specified duration of a QoS session has reached its limit or the default session expiration time has been reached (within an example provider implementation it is set to 24hrs).

    # Relevant terms and definitions

    * **QOD service endpoint**:
    The URL pointing to the RESTful resource of the QoD API.

    * **Authentication**:
    Security access keys such as OAuth 2.0 client credentials used by client applications to invoke the QoD API.

    * **QoS profiles and QoS profile labels**:
    Latency or throughput requirements of the application mapped to relevant QoS profile class.

    * **Identifier for the device**:
    At least one identifier for the device (user equipment) out of four options: IPv4 address, IPv6 address, Phone number, or Network Access Identifier [[5]](#5) assigned by the mobile network operator for the device.

    * **Identifier for the application server**:
    IPv4 and/or IPv6 address of the application server (application backend)

    * **App-Flow (between the application client and application server)**:
    The precise application data flow the developer wants to prioritize and have stable latency or throughput for. This flow is in the current API version determined by the identifiers used for the device and the application server. And it can be further elaborated with details such as ports or port-ranges. Future version of the API might allow more detailed flow identification features.

    * **Duration**:
    Duration (in seconds) for which the QoS session (between application client and application server) should be created. This parameter is optional. When not specified, a default session duration (e.g. 24 hours) is applied. The user may request a termination before its expiration.

    * **Notification URL and token**:
    Developers may provide a callback URL on which notifications about all status change events of the session (eg. session termination) can be received from the service provider. This is an optional parameter.

    # API functionality

    The usage of the QoD API is based on QoS profile classes and parameters which define App-Flows.
    Based on the API, QoS session resources can be created, queried, and deleted. Once an offered QoS profile class is requested, application users get a prioritized service with stable latency or throughput even in the case of congestion. The QoD API has the following characteristics:

    * A specified App-Flow is prioritized to ensure stable latency or throughput for that flow.
    * The prioritized App-Flow is described by providing information such as device IP address (or other device identifier) & application server IP addresses and port/port-ranges.
    * The developer can optionally specify the duration for which they need the prioritized App-flow.
    * Stable latency or throughput is requested by selecting from the list of QoS profiles made available by the service provider (e.g. QOS_E) to map latency and throughput requirements.
    * The developer can optionally also specify callback URL on which notifications for the session can be sent. <br>

    Following diagram shows the interaction between different components

    ![QoD Management API](https://raw.githubusercontent.com/camaraproject/QualityOnDemand/main/documentation/API_documentation/resources/QoD_details.PNG)

    How QoS profiles are mapped to connectivity characteristics are subject to agreements between the communication service provider and the API invoker. Within the CAMARA project, you can find a sample for such a mapping of QoS profiles. [CAMARA QoS Profiles Mapping Table (REFERENCE DRAFT)](https://github.com/camaraproject/QualityOnDemand/blob/main/documentation/API_documentation/QoSProfile_Mapping_Table.md)

    # Further info and support

    (FAQs will be added in a later version of the documentation)
  termsOfService: http://swagger.io/terms/
  contact:
    email: project-email@sample.com
  license:
    name: Apache 2.0
    url: https://www.apache.org/licenses/LICENSE-2.0.html
  version: 0.10.1-wip
externalDocs:
  description: Product documentation at Camara
  url: https://github.com/camaraproject/
security:
  - oAuth2ClientCredentials: [ ]
servers:
  - url: "{apiRoot}/qod/v0"
    variables:
      apiRoot:
        default: https://api.orange.com/camara/quality-on-demand/orange-lab
        description: API root, defined by the service provider, e.g. `api.example.com` or `api.example.com/somepath`
tags:
  - name: QoS Sessions
    description: Manage QoS sessions
  - name: QoS Profiles
    description: Manage QoS Profiles
paths:
  /sessions:
    post:
      tags:
        - QoS Sessions
      summary: Creates a new session
      description: |
        Create QoS Session to manage latency/throughput priorities

        If the qosStatus in the API response is "AVAILABLE" and a notification callback is provided the client will receive in addition to the response a
        `QOS_STATUS_CHANGED` event notification with `qosStatus` as `AVAILABLE`.

        If the `qosStatus` in the API response is `REQUESTED`, the client will receive either
        - a `QOS_STATUS_CHANGED` event notification with `qosStatus` as `AVAILABLE` after the network notifies that it has created the requested session, or
        - a `QOS_STATUS_CHANGED` event notification with `qosStatus` as `UNAVAILABLE` and `statusInfo` as `NETWORK_TERMINATED` after the network notifies that it has failed to provide the requested session.

        A `QOS_STATUS_CHANGED` event notification with `qosStatus` as `UNAVAILABLE` will also be send if the network terminates the session before the requested duration expired

        NOTE: in case of a `QOS_STATUS_CHANGED` event with `qosStatus` as `UNAVAILABLE` and `statusInfo` as `NETWORK_TERMINATED` the resources of the QoS session
        are not directly released, but will get deleted automatically at earliest 360 seconds after the event.
        This behavior allows clients which are not receiving notification events but are polling to get the session information with
        the `qosStatus` `UNAVAILABLE` (the `statusInfo` parameter is not included in the current version but will be adding to `SessionInfo` in an upcoming release). Before a client can attempt to create a new QoD session
        for the same device and flow period they must release the session resources with an explicit `delete` operation if not yet automatically deleted.

      operationId: createSession
      requestBody:
        description: Parameters to create a new session
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateSession"
        required: true
      callbacks:
        notifications:
          "{$request.body#/webhook/notificationUrl}":
            post:
              tags:
                - Session notifications callback
              summary: "Session notifications callback"
              description: |
                Important: this endpoint is to be implemented by the API consumer.
                The QoD server will call this endpoint whenever any QoS session change (e.g. network termination) related event occurs.
                Currently only QOS_STATUS_CHANGED event is defined.
              operationId: postNotification
              requestBody:
                required: true
                content:
                  application/cloudevents+json:
                    schema:
                      $ref: "#/components/schemas/CloudEvent"
                    examples:
                      QOS_STATUS_CHANGED_EXAMPLE:
                        $ref: "#/components/examples/QOS_STATUS_CHANGED_EXAMPLE"
              responses:
                "204":
                  description: Successful notification
                "400":
                  $ref: "#/components/responses/Generic400"
                "401":
                  $ref: "#/components/responses/Generic401"
                "403":
                  $ref: "#/components/responses/Generic403"
                "500":
                  $ref: "#/components/responses/Generic500"
                "503":
                  $ref: "#/components/responses/Generic503"
              security:
                - { }
                - notificationsBearerAuth: [ ]
      responses:
        "201":
          description: Session created
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SessionInfo"
        "400":
          description: Invalid input for createSession operation
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorInfo"
              examples:
                Generic400:
                  summary: Some parameter combinations or parameter values provided are not schema compliant
                  value:
                    status: 400
                    code: INVALID_ARGUMENT
                    message: "Schema validation failed at  ..."
                DeviceMissing:
                  summary: Device must be specified
                  value:
                    status: 400
                    code: INVALID_ARGUMENT
                    message: "Expected property is missing: device"
                InsufficientDeviceProperties:
                  summary: Device must be identified by at least one parameter
                  value:
                    status: 400
                    code: INVALID_ARGUMENT
                    message: "Insufficient properties specified: device"
                InconsistentDeviceProperties:
                  summary: Device parameters provided identify different devices
                  value:
                    status: 400
                    code: INVALID_ARGUMENT
                    message: "Multiple inconsistent parameters specified: device"
                CannotIdentifyDevice:
                  summary: No device can be identified from provided parameters
                  value:
                    status: 400
                    code: INVALID_ARGUMENT
                    message: "Unable to identify device from specified parameters: device"
                InvalidDevicePublicPortValue:
                  summary: Invalid port specified for device public port
                  value:
                    status: 400
                    code: OUT_OF_RANGE
                    message: "Invalid port value specified: device.ipv4Address.publicPort"
                ApplicationServerMissing:
                  summary: Application server must be specified
                  value:
                    status: 400
                    code: INVALID_ARGUMENT
                    message: "Expected property is missing: applicationServer"
                QoSProfileMissing:
                  summary: Required QoS profile must be specified
                  value:
                    status: 400
                    code: INVALID_ARGUMENT
                    message: "Expected property is missing: qosProfile"
                InvalidDevicePortsRanges:
                  summary: Invalid port ranges specified for devicePorts
                  value:
                    status: 400
                    code: OUT_OF_RANGE
                    message: "Invalid port ranges specified: devicePorts"
                DurationOutOfRangeForQoSProfile:
                  summary: The requested duration is out of the allowed range for the specific QoS profile
                  value:
                    status: 400
                    code: OUT_OF_RANGE
                    message: "The requested duration is out of the allowed range for the specific QoS profile"
        "401":
          $ref: "#/components/responses/Generic401"
        "403":
          $ref: "#/components/responses/Generic403"
        "409":
          description: Conflict
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorInfo"
              example:
                status: 409
                code: CONFLICT
                message: "Another session is created for the same device"
        "500":
          $ref: "#/components/responses/Generic500"
        "501":
          $ref: "#/components/responses/Generic501"
        "503":
          $ref: "#/components/responses/Generic503"
      security:
        - oAuth2ClientCredentials: [ ]
        - threeLegged:
            - "qod-sessions-write"

  /sessions/{sessionId}:
    get:
      tags:
        - QoS Sessions
      summary: Get QoS session information
      description: Querying for QoS session resource information details
      operationId: getSession
      parameters:
        - name: sessionId
          in: path
          description: Session ID that was obtained from the createSession operation
          required: true
          schema:
            $ref: "#/components/schemas/SessionId"
      responses:
        "200":
          description: Contains information about active session
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SessionInfo"
        "400":
          $ref: "#/components/responses/Generic400"
        "401":
          $ref: "#/components/responses/Generic401"
        "403":
          $ref: "#/components/responses/Generic403"
        "404":
          $ref: "#/components/responses/SessionNotFound404"
        "500":
          $ref: "#/components/responses/Generic500"
        "503":
          $ref: "#/components/responses/Generic503"
      security:
        - oAuth2ClientCredentials: [ ]
        - threeLegged:
            - "qod-sessions-read"

    delete:
      tags:
        - QoS Sessions
      summary: Delete a QoS session
      description: |
        Release resources related to QoS session

        If the notification callback is provided and the `qosStatus` of the session was `AVAILABLE` the client will receive in addition to the response a `QOS_STATUS_CHANGED` event with
        - `qosStatus` as `UNAVAILABLE` and
        - `statusInfo` as `DELETE_REQUESTED`
        There will be no notification event if the `qosStatus` was already `UNAVAILABLE`.
      operationId: deleteSession
      parameters:
        - name: sessionId
          in: path
          description: Session ID that was obtained from the createSession operation
          required: true
          schema:
            $ref: "#/components/schemas/SessionId"
      responses:
        "204":
          description: Session deleted
        "400":
          $ref: "#/components/responses/Generic400"
        "401":
          $ref: "#/components/responses/Generic401"
        "403":
          $ref: "#/components/responses/Generic403"
        "404":
          $ref: "#/components/responses/SessionNotFound404"
        "500":
          $ref: "#/components/responses/Generic500"
        "503":
          $ref: "#/components/responses/Generic503"
      security:
        - oAuth2ClientCredentials: [ ]
        - threeLegged:
            - "qod-sessions-delete"

  /sessions/{sessionId}/extend:
    post:
      tags:
        - QoS Sessions
      summary: "Extend the duration of an active session"
      description: |
        Extend the duration of an active QoS session. If this operation is executed successfully, the new duration of the target session will be the original duration plus the additional duration. The remaining duration plus the requested additional duration shall not exceed the maximum limit. Otherwise, the new remaining duration will be the maximum limit.
      operationId: extendQosSessionDuration
      parameters:
        - name: sessionId
          in: path
          description: Session ID that was obtained from the createSession operation
          required: true
          schema:
            $ref: "#/components/schemas/SessionId"
      requestBody:
        description: Parameters to extend the duration of an active session
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ExtendSessionDuration"
        required: true
      responses:
        "200":
          description: Contains information about active session
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SessionInfo"
        "400":
          description: Invalid input for extendQosSessionDuration operation
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorInfo"
              examples:
                Generic400:
                  summary: Some parameter combinations or parameter values provided are not schema compliant
                  value:
                    status: 400
                    code: INVALID_ARGUMENT
                    message: "Schema validation failed at  ..."
                InactiveSession:
                  summary: The target session is inactive
                  value:
                    status: 400
                    code: INVALID_ARGUMENT
                    message: "The target session is inactive"
        "401":
          $ref: "#/components/responses/Generic401"
        "403":
          $ref: "#/components/responses/Generic403"
        "404":
          $ref: "#/components/responses/SessionNotFound404"
        "500":
          $ref: "#/components/responses/Generic500"
        "503":
          $ref: "#/components/responses/Generic503"
      security:
        - oAuth2ClientCredentials: [ ]
        - threeLegged:
            - "qod-sessions-write"

  /qos-profiles:
    get:
      tags:
        - QoS Profiles
      summary: "Get All QoS Profiles"
      description: |
        Returns all QoS Profiles that match the given criteria.
        If no criteria is given, all QoS Profiles are returned.
      operationId: getQosProfiles
      parameters:
        - name: name
          in: query
          description: QoS Profile name
          schema:
            type: string
          required: false
        - name: status
          in: query
          schema:
            $ref: '#/components/schemas/QosProfileStatusEnum'
          required: false
      responses:
        "200":
          description: Contains information about QoS Profiles
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/QosProfile"
        "401":
          $ref: "#/components/responses/Generic401"
        "403":
          $ref: "#/components/responses/Generic403"
        "404":
          $ref: "#/components/responses/QosProfilesNotFound404"
        "500":
          $ref: "#/components/responses/QoSProfile500"
        "503":
          $ref: "#/components/responses/Generic503"

  /qos-profiles/{name}:
    get:
      tags:
        - QoS Profiles
      summary: "Get QoS Profile for a given name"
      operationId: getQosProfile
      description: |
        Returns a QoS Profile that matches the given name.
      parameters:
        - name: name
          in: path
          required: true
          schema:
            $ref: "#/components/schemas/QosProfileName"
      responses:
        "200":
          description: Contains information about QoS Profiles
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/QosProfile"
        "400":
          $ref: "#/components/responses/Generic400"
        "401":
          $ref: "#/components/responses/Generic401"
        "403":
          $ref: "#/components/responses/Generic403"
        "404":
          $ref: "#/components/responses/QosProfileNotFound404"
        "500":
          $ref: "#/components/responses/QoSProfile500"
        "503":
          $ref: "#/components/responses/Generic503"

components:
  securitySchemes:
    oAuth2ClientCredentials:
      description: |
        The QoD API makes use of the OAUTH 2.0 client credentials grant which is applicable for server to server use cases involving trusted partners or clients without any protected user data involved. In this method the API invoker client is registered as a confidential client with an authorization grant type of client_credentials
      type: oauth2
      flows:
        clientCredentials:
          tokenUrl: https://api.example.com/oauth/token
          scopes: { }
    notificationsBearerAuth:
      type: http
      scheme: bearer
      bearerFormat: "{$request.body#/webhook/notificationAuthToken}"
    threeLegged:
      type: oauth2
      description: This API uses OAuth 2 with the authorization code grant flow.
      flows:
        authorizationCode:
          authorizationUrl: https://api.example.com/oauth2/authorize
          tokenUrl: https://api.example.com/oauth/token
          scopes:
            qod-sessions-read: Retrieval of QoS sessions
            qod-sessions-write: Creation and update of QoS sessions
            qod-sessions-delete: Deletion of QoS sessions
            qod-profiles-read: Retrieval of QoS profiles

  schemas:
    SessionId:
      description: Session ID in UUID format
      type: string
      format: uuid

    SessionInfo:
      description: Session related information.
      allOf:
        - $ref: "#/components/schemas/CreateSession"
        - type: object
          properties:
            sessionId:
              $ref: "#/components/schemas/SessionId"
            startedAt:
              type: integer
              example: 1639479600
              description: Timestamp of session start in seconds since Unix epoch
              format: int64
            expiresAt:
              type: integer
              example: 1639566000
              description: Timestamp of session expiration if the session was not deleted, in seconds since Unix epoch
              format: int64
            qosStatus:
              $ref: "#/components/schemas/QosStatus"
            messages:
              type: array
              items:
                $ref: "#/components/schemas/Message"
          required:
            - sessionId
            - duration
            - startedAt
            - expiresAt
            - qosStatus

    CreateSession:
      description: Attributes required to create a session
      type: object
      properties:
        duration:
          description: |
            Session duration in seconds. Maximal value of 24 hours is used if not set.
            After session is expired the, client will receive a `QOS_STATUS_CHANGED` event with
             - `qosStatus` as `UNAVAILABLE`, and,
             - `statusInfo` as `DURATION_EXPIRED`.
            See notification callback.
          type: integer
          format: int32
          minimum: 1
          maximum: 86400
          default: 86400
          example: 86400
        device:
          $ref: "#/components/schemas/Device"
        applicationServer:
          $ref: "#/components/schemas/ApplicationServer"
        devicePorts:
          description: The ports used locally by the device for flows to which the requested QoS profile should apply. If omitted, then the qosProfile will apply to all flows between the device and the specified application server address and ports
          allOf:
            - $ref: "#/components/schemas/PortsSpec"
        applicationServerPorts:
          description: A list of single ports or port ranges on the application server
          allOf:
            - $ref: "#/components/schemas/PortsSpec"
        qosProfile:
          $ref: "#/components/schemas/QosProfileName"
        webhook:
          type: object
          required:
            - notificationUrl
          properties:
            notificationUrl:
              type: string
              format: uri
              example: "https://application-server.com"
              description: Allows asynchronous delivery of session related events
            notificationAuthToken:
              type: string
              minLength: 20
              maxLength: 256
              example: "c8974e592c2fa383d4a3960714"
              description: Authentication token for callback API
      required:
        - device
        - applicationServer
        - qosProfile

    Port:
      description: TCP or UDP port number
      type: integer
      minimum: 0
      maximum: 65535

    PortsSpec:
      type: object
      minProperties: 1
      properties:
        ranges:
          type: array
          minItems: 1
          items:
            type: object
            required:
              - from
              - to
            properties:
              from:
                $ref: "#/components/schemas/Port"
              to:
                $ref: "#/components/schemas/Port"
        ports:
          type: array
          minItems: 1
          items:
            $ref: "#/components/schemas/Port"
      example:
        ranges:
          - from: 5010
            to: 5020
        ports:
          - 5060
          - 5070

    ExtendSessionDuration:
      description: Attributes required to extend the duration of an active session
      type: object
      properties:
        requestedAdditionalDuration:
          description: |
            Additional duration in seconds to be extended.
          type: integer
          format: int32
          minimum: 1
          maximum: 86399
          example: 60
      required:
        - requestedAdditionalDuration


    QosProfile:
      description: |
        Data type with attributes of a QosProfile
      type: object
      properties:
        name:
          $ref: "#/components/schemas/QosProfileName"
        description:
          description: |
            A description of the QoS profile.
          type: string
          example: "QoS profile for video streaming"
        status:
          $ref: "#/components/schemas/QosProfileStatusEnum"
        targetMinUpstreamRate:
          description: |
            This is the target minimum upstream rate for the QoS profile.
            For 5G networks 3GPP Guaranteed Bit Rate (GBR) refers to a dedicated, fixed data rate assigned to
            specific services, ensuring a minimum performance level. As per 3GPP TS 23.203,
            GBR is a QoS parameter used to manage traffic classes in mobile networks. It
            provides a stable data rate for latency-sensitive applications, such as voice calls or
            video streaming, helping maintain a consistent user experience. When this attribute is set
            this could imply that a GBR QCI is used, though mechanisms on the network can be used to
            ensure a minimum performance level without using a GBR QCI.
            The committed data rate allocated to specific services, ensuring a consistent level of
            performance. For DOCSIS networks, the "Minimum Reserved Traffic Rate" is defined in the
            DOCSIS 3.1 - MAC and Upper Layer Protocols Interface Specification"
            and it ensures a consistent level of performance for specific services within the network.
          allOf:
            - $ref: "#/components/schemas/Rate"
        maxUpstreamRate:
          description: |
            The maximum best effort data
          allOf:
            - $ref: "#/components/schemas/Rate"
        maxUpstreamBurstRate:
          description: |
            When defined, this is the maximum upstream burst rate for the QoS profile, that will enable
            the network to burst data at a higher rate than the maxUpstreamRate for a period of time.
          allOf:
            - $ref: "#/components/schemas/Rate"
        targetMinDownstreamRate:
          description: |
            This is the target minimum downstream rate for the QoS profile.
            For 5G networks 3GPP Guaranteed Bit Rate (GBR) refers to a dedicated, fixed data rate assigned to
            specific services, ensuring a minimum performance level. As per 3GPP TS 23.203,
            GBR is a QoS parameter used to manage traffic classes in mobile networks. It
            provides a stable data rate for latency-sensitive applications, such as voice calls or
            video streaming, helping maintain a consistent user experience.  When this attribute is set
            this could imply that a GBR QCI is used, though mechanisms on the network can be used to
            ensure a minimum performance level without using a GBR QCI.
            The committed data rate allocated to specific services, ensuring a consistent level of
            performance. DOCSIS networks, the "Minimum Reserved Traffic Rate" is defined in the
            DOCSIS 3.1 - MAC and Upper Layer Protocols Interface Specification"
            and it ensures a consistent level of performance for specific services within the network.
          allOf:
            - $ref: "#/components/schemas/Rate"
        maxDownstreamRate:
          description: |
            The maximum best effort rate
          allOf:
            - $ref: "#/components/schemas/Rate"
        maxDownstreamBurstRate:
          description: |
            When defined, this is the maximum downstream burst rate for the QoS profile, that will enable
            the network to burst data at a higher rate than the maxDownstreamRate for a period of time.
            This can result in improved user experience when there is additional network capacity.
            For instance, when a user is streaming a video, the network can burst data at a higher rate
            to fill the buffer, and then return to the maxUpstreamRate once the buffer is full.
          allOf:
            - $ref: "#/components/schemas/Rate"
        minDuration:
          description: |
            The shortest time period that this profile can be deployed.
          allOf:
            - $ref: "#/components/schemas/Duration"
        maxDuration:
          description: |
            The maximum time period that this profile can be deployed.
            NOTE: currently the duration within `sessionInfo` is limited to 86400 seconds (1 day).
            The value of `maxDuration` shouldn't therefore exceed this time period. The limitation might be removed in later versions.
          allOf:
            - $ref: "#/components/schemas/Duration"
        priority:
          type: integer
          example: 20
          description: |
            Priority levels allow efficient resource allocation and ensure optimal performance
            for various services in each technology, with the highest priority traffic receiving
            preferential treatment.
            The lower value the higher priority.
            Not all access networks use the same priority range, so this priority will be
            scaled to the access network's priority range.
          format: int32
          minimum: 1
          maximum: 100
        packetDelayBudget:
          description: |
            The packet delay budget is the maximum allowable one-way latency between the customer's device
            and the gateway from the operator's network to other networks. By limiting the delay, the network
            can provide an acceptable level of performance for various services, such as voice calls,
            video streaming, and data.
            The end-to-end or round trip latency will be about two times this value plus the latency not controlled
            by the operator
          allOf:
            - $ref: "#/components/schemas/Duration"
        jitter:
          description: |
            The jitter requirement aims to limit the maximum variation in round-trip
            packet delay for the 99th percentile of traffic, following ITU Y.1540
            standards. It considers only acknowledged packets in a session, which are
            packets that receive a confirmation of receipt from the recipient (e.g.,
            using TCP). This requirement helps maintain consistent latency, essential
            for real-time applications such as VoIP, video calls, and gaming.
          allOf:
            - $ref: "#/components/schemas/Duration"
        packetErrorLossRate:
          type: integer
          description: |
            The exponential power of the allowable error loss rate 10^(-N).
            For instance 3 would be an error loss rate of 10 to the power of -3 (0.001)

            For 5G network the 3GPP specification TS 23.203 defines the packet error loss rate QCI attribute. It
            describes the Quality of Service (QoS) Class Identifier (QCI) parameters used to
            differentiate traffic classes in mobile networks, ensuring appropriate resource
            allocation and performance for various services.

            The packet error loss rate is one of the QCI attributes, providing information on the
            acceptable packet loss rate for a specific traffic class. This attribute helps maintain
            the desired performance level for services like voice calls, video streaming, or data
            transfers within the 3GPP mobile network.
          format: int32
          minimum: 1
          maximum: 10
          example: 3
      required:
        - name
        - status

    QosProfileName:
      description: |
        A unique name for identifying a specific QoS profile.
        This may follow different formats depending on the service providers implementation.
        Some options addresses:
          - A UUID style string
          - Support for predefined profiles QOS_S, QOS_M, QOS_L, and QOS_E
          - A searchable descriptive name
      type: string
      example: QCI_1_voice
      minLength: 3
      maxLength: 256
      format: string
      pattern: "^[a-zA-Z0-9_.-]+$"

    Rate:
      type: object
      properties:
        value:
          type: integer
          example: 10
          format: int32
          minimum: 0
          maximum: 1024
        unit:
          $ref: "#/components/schemas/RateUnitEnum"

    Duration:
      type: object
      properties:
        value:
          type: integer
          example: 12
          format: int32
          minimum: 1
        unit:
          allOf:
            - $ref: "#/components/schemas/TimeUnitEnum"
            - example: Minutes

    TimeUnitEnum:
      type: string
      enum:
        - Days
        - Hours
        - Minutes
        - Seconds
        - Milliseconds
        - Microseconds
        - Nanoseconds

    QosProfileStatusEnum:
      description: |
        The current status of the QoS Profile
        - `ACTIVE`- QoS Profile is available to be used
        - `INACTIVE`- QoS Profile is not currently available to be deployed
        - `DEPRECATED`- QoS profile is actively being used in a QoD session, but can not be deployed in new QoD sessions
      type: string
      enum:
        - ACTIVE
        - INACTIVE
        - DEPRECATED

    RateUnitEnum:
      type: string
      enum:
        - bps
        - kbps
        - Mbps
        - Gbps
        - Tbps

    CloudEvent:
      description: Event compliant with the CloudEvents specification
      required:
        - id
        - source
        - specversion
        - type
        - time
      properties:
        id:
          description: Identifier of this event, that must be unique in the source context.
          type: string
        source:
          description: Identifies the context in which an event happened in the specific Provider Implementation.
          type: string
          format: uri-reference
        type:
          description: The type of the event.
          type: string
          enum:
            - 'org.camaraproject.qod.v0.qos-status-changed'
        specversion:
          description: Version of the specification to which this event conforms (must be 1.0 if it conforms to cloudevents 1.0.2 version)
          type: string
          enum:
            - '1.0'
        datacontenttype:
          description: 'media-type that describes the event payload encoding, must be "application/json" for CAMARA APIs'
          type: string
          enum:
            - 'application/json'
        data:
          description: Event notification details payload, which depends on the event type
          type: object
        time:
          description: |
            Timestamp of when the occurrence happened. It must follow RFC 3339
          type: string
          format: date-time
      discriminator:
        propertyName: 'type'
        mapping:
          org.camaraproject.qod.v0.qos-status-changed: '#/components/schemas/EventQosStatusChanged'

    EventQosStatusChanged:
      allOf:
        - $ref: "#/components/schemas/CloudEvent"
        - type: object
          properties:
            data:
              $ref: "#/components/schemas/QosStatusChangedData"
          required:
            - data

    QosStatusChangedData:
      type: object
      description: Status changed specific data
      required:
        - sessionId
        - qosStatus
      properties:
        sessionId:
          $ref: "#/components/schemas/SessionId"
        qosStatus:
          $ref: "#/components/schemas/EventQosStatus"
        statusInfo:
          $ref: "#/components/schemas/StatusInfo"

    StatusInfo:
      description: |
        Reason for the new `qosStatus`. Currently `statusInfo` is only applicable when `qosStatus` is 'UNAVAILABLE'.
        * `DURATION_EXPIRED` - Session terminated due to requested duration expired
        * `NETWORK_TERMINATED` - Network terminated the session before the requested duration expired
        * `DELETE_REQUESTED`- User requested the deletion of the session before the requested duration expired

      type: string
      enum:
        - DURATION_EXPIRED
        - NETWORK_TERMINATED
        - DELETE_REQUESTED

    Device:
      description: |
        End-user equipment able to connect to a mobile network. Examples of devices include smartphones or IoT sensors/actuators.

        The developer can choose to provide the below specified device identifiers:

        * `ipv4Address`
        * `ipv6Address`
        * `phoneNumber`
        * `networkAccessIdentifier`

        NOTE: the MNO might support only a subset of these options. The API invoker can provide multiple identifiers to be compatible across different MNOs. In this case the identifiers MUST belong to the same device
      type: object
      properties:
        phoneNumber:
          $ref: "#/components/schemas/PhoneNumber"
        networkAccessIdentifier:
          $ref: "#/components/schemas/NetworkAccessIdentifier"
        ipv4Address:
          $ref: "#/components/schemas/DeviceIpv4Addr"
        ipv6Address:
          $ref: "#/components/schemas/DeviceIpv6Address"
      minProperties: 1

    ApplicationServer:
      description: |
        A server hosting backend applications to deliver some business logic to clients.

        The developer can choose to provide the below specified device identifiers:

        * `ipv4Address`
        * `ipv6Address`
      type: object
      properties:
        ipv4Address:
          $ref: "#/components/schemas/ApplicationServerIpv4Address"
        ipv6Address:
          $ref: "#/components/schemas/ApplicationServerIpv6Address"
      minProperties: 1

    NetworkAccessIdentifier:
      description: A public identifier addressing a subscription in a mobile network. In 3GPP terminology, it corresponds to the GPSI formatted with the External Identifier ({Local Identifier}@{Domain Identifier}). Unlike the telephone number, the network access identifier is not subjected to portability ruling in force, and is individually managed by each operator.
      type: string
      example: "123456789@domain.com"

    PhoneNumber:
      description: A public identifier addressing a telephone subscription. In mobile networks it corresponds to the MSISDN (Mobile Station International Subscriber Directory Number). In order to be globally unique it has to be formatted in international format, according to E.164 standard, optionally prefixed with '+'.
      type: string
      pattern: '^\+?[0-9]{5,15}$'
      example: "123456789"

    DeviceIpv4Addr:
      type: object
      description: |
        The device should be identified by either the public (observed) IP address and port as seen by the application server, or the private (local) and any public (observed) IP addresses in use by the device (this information can be obtained by various means, for example from some DNS servers).

        If the allocated and observed IP addresses are the same (i.e. NAT is not in use) then  the same address should be specified for both publicAddress and privateAddress.

        If NAT64 is in use, the device should be identified by its publicAddress and publicPort, or separately by its allocated IPv6 address (field ipv6Address of the Device object)

        In all cases, publicAddress must be specified, along with at least one of either privateAddress or publicPort, dependent upon which is known. In general, mobile devices cannot be identified by their public IPv4 address alone.
      properties:
        publicAddress:
          $ref: "#/components/schemas/SingleIpv4Addr"
        privateAddress:
          $ref: "#/components/schemas/SingleIpv4Addr"
        publicPort:
          $ref: "#/components/schemas/Port"
      anyOf:
        - required: [ publicAddress, privateAddress ]
        - required: [ publicAddress, publicPort ]
      example:
        {
          "publicAddress": "84.125.93.10",
          "publicPort": 59765
        }

    SingleIpv4Addr:
      description: A single IPv4 address with no subnet mask
      type: string
      format: ipv4
      example: "84.125.93.10"

    DeviceIpv6Address:
      description: |
        The device should be identified by the observed IPv6 address, or by any single IPv6 address from within the subnet allocated to the device (e.g. adding ::0 to the /64 prefix).

        The session shall apply to all IP flows between the device subnet and the specified application server, unless further restricted by the optional parameters devicePorts or applicationServerPorts.
      type: string
      format: ipv6
      example: 2001:db8:85a3:8d3:1319:8a2e:370:7344

    ApplicationServerIpv4Address:
      type: string
      example: "192.168.0.1/24"
      description: |
        IPv4 address may be specified in form <address/mask> as:
          - address - an IPv4 number in dotted-quad form 1.2.3.4. Only this exact IP number will match the flow control rule.
          - address/mask - an IP number as above with a mask width of the form 1.2.3.4/24.
            In this case, all IP numbers from 1.2.3.0 to 1.2.3.255 will match. The bit width MUST be valid for the IP version.

    ApplicationServerIpv6Address:
      type: string
      example: "2001:db8:85a3:8d3:1319:8a2e:370:7344"
      description: |
        IPv6 address may be specified in form <address/mask> as:
          - address - The /128 subnet is optional for single addresses:
            - 2001:db8:85a3:8d3:1319:8a2e:370:7344
            - 2001:db8:85a3:8d3:1319:8a2e:370:7344/128
          - address/mask - an IP v6 number with a mask:
            - 2001:db8:85a3:8d3::0/64
            - 2001:db8:85a3:8d3::/64

    Message:
      type: object
      properties:
        severity:
          description: Message severity
          type: string
          enum: [ "INFO", "WARNING" ]
        description:
          description: Detailed message text
          type: string
      required:
        - severity
        - description

    QosStatus:
      description: |
        The current status of the requested QoS session. The status can be one of the following:
        * `REQUESTED` - QoS has been requested by creating a session
        * `AVAILABLE` - The requested QoS has been provided by the network
        * `UNAVAILABLE` - The requested QoS cannot be provided by the network due to some reason
      type: string
      enum:
        - REQUESTED
        - AVAILABLE
        - UNAVAILABLE

    EventQosStatus:
      description: |
        The current status of a requested or previously available session. Applicable values in the event are:
        *  `AVAILABLE` - The requested QoS has been provided by the network.
        *  `UNAVAILABLE` - A requested or previously available QoS session is now unavailable. `statusInfo` may provide additional information about the reason for the unavailability.
      type: string
      enum:
        - AVAILABLE
        - UNAVAILABLE

    ErrorInfo:
      type: object
      properties:
        status:
          type: integer
          description: HTTP status code returned along with this error response
        code:
          type: string
          description: Code given to this error
        message:
          type: string
          description: Detailed error description
      required:
        - status
        - code
        - message

  responses:
    Generic400:
      description: Invalid input
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorInfo"
          example:
            status: 400
            code: INVALID_ARGUMENT
            message: "Schema validation failed at  ..."

    Generic401:
      description: Unauthorized
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorInfo"
          example:
            status: 401
            code: UNAUTHENTICATED
            message: "Authorization failed: ..."

    Generic403:
      description: Forbidden
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorInfo"
          example:
            status: 403
            code: PERMISSION_DENIED
            message: "Operation not allowed: ..."

    SessionNotFound404:
      description: Session not found
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorInfo"
          example:
            status: 404
            code: NOT_FOUND
            message: "Session Id does not exist"

    QosProfilesNotFound404:
      description: Qos Profiles not found
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorInfo"
          example:
            status: 404
            code: NOT_FOUND
            message: "No QoS Profiles found"

    QosProfileNotFound404:
      description: Qos Profile not found
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorInfo"
          example:
            status: 404
            code: NOT_FOUND
            message: "QosProfile Id does not exist"

    Generic500:
      description: Internal server error
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorInfo"
          example:
            status: 500
            code: INTERNAL
            message: "Internal server error: ..."

    QoSProfile500:
      description: Internal server error
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorInfo"
          example:
            status: 500
            code: INTERNAL
            message: "Internal server error: Could not get QoS Profile"

    Generic501:
      description: Not Implemented
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorInfo"
          example:
            status: 501
            code: NOT_IMPLEMENTED
            message: "Service not implemented for the specified user device"

    Generic503:
      description: Service unavailable
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorInfo"
          example:
            status: 503
            code: UNAVAILABLE
            message: "Service unavailable"

  examples:
    QOS_STATUS_CHANGED_EXAMPLE:
      summary: QoS status changed
      value:
        id: 83a0d986-0866-4f38-b8c0-fc65bfcda452
        source: 'https://api.example.com/qod/v0/sessions/123e4567-e89b-12d3-a456-426614174000'
        specversion: '1.0'
        type: 'org.camaraproject.qod.v0.qos-status-changed'
        time: '2021-12-12T00:00:00Z'
        data:
          sessionId: '123e4567-e89b-12d3-a456-426614174000'
          qosStatus: 'UNAVAILABLE'
          statusInfo: 'DURATION_EXPIRED'
